home *** CD-ROM | disk | FTP | other *** search
/ Nebula 2 / Nebula Two.iso / SourceCode / Random2.0 / Source / ElkinsEngine.m < prev    next >
Text File  |  1995-06-12  |  4KB  |  222 lines

  1. //
  2. // ElkinsEngine
  3. //
  4. // Copyright (C) 1992 Contemporary Design Studios. All rights reserved.
  5. //
  6.  
  7.  
  8. #import "ElkinsEngine.h"
  9. #import <sys/time.h>
  10. #import <stdio.h>
  11.  
  12.  
  13. //
  14. // Constants:
  15. //
  16. // See the journal article referenced in the header file.
  17. //
  18.  
  19. #define M1    32771
  20. #define M2    32779
  21. #define M3    32783
  22. #define F1    179
  23. #define F2    183
  24. #define F3    182
  25.  
  26. #define RANGE    32768
  27.  
  28. //#define RANGE    65536
  29. #define MAXNUM    (RANGE - 1)
  30.  
  31.  
  32. @implementation ElkinsEngine
  33.  
  34.  
  35. //
  36. // unit
  37. //
  38. // The ElkinsEngine, as defined in the article only uses 15 of the 16 bits
  39. // in an unsigned short. We want full bytes of random bits, so we must
  40. // throw away the partial byte.
  41. //
  42.  
  43. + (ulong)unit
  44. {
  45.     return 30;
  46. }
  47.  
  48.  
  49. //
  50. // init
  51. //
  52.  
  53. - init
  54. {
  55.     [super init];
  56.     [self newSeeds];
  57.     
  58.     return self;
  59. }
  60.  
  61.  
  62. //
  63. // initSeeds:::
  64. //
  65.  
  66. - initSeeds:(ushort)s1
  67.   :(ushort)s2
  68.   :(ushort)s3
  69. {
  70.     [super init];
  71.     [self setSeeds:s1 :s2 :s3];
  72.  
  73.     return self;
  74. }
  75.  
  76.  
  77. //
  78. // newSeeds
  79. //
  80.  
  81. - newSeeds
  82. {
  83.     struct timeval theTime;        // gettimeofday return structure
  84. //    ushort foo;
  85.     
  86.     gettimeofday(&theTime, 0);        // Get the time of day in seconds and microseconds
  87.     h1 = theTime.tv_usec % RANGE;    // Set seed 1 by microseconds past second
  88.     gettimeofday(&theTime, 0);        // Get the time of day in seconds and microseconds
  89.     h2 = theTime.tv_usec % RANGE;    // Set seed 2 by microseconds past second
  90.     gettimeofday(&theTime, 0);        // Get the time of day in seconds and microseconds
  91.     h3 = theTime.tv_usec % RANGE;    // Set seed 3 by microseconds past second
  92.  
  93. //    printf("ElkinsEngine: Seeds set to: %d %d %d\n", (long)h1, (long)h2, (long)h3);
  94.  
  95. //    [self makeRandom:(char *)(&foo)];
  96.  
  97.     return self;    
  98. }
  99.  
  100.  
  101. //
  102. // setSeeds:::
  103. //
  104.  
  105. - setSeeds:(ushort) s1 :(ushort) s2 :(ushort) s3
  106. {
  107. //    ushort    foo;
  108.     
  109.     h1 = s1;                // Set the seeds to the values given
  110.     h2 = s2;
  111.     h3 = s3;
  112.     
  113. //    [self makeRandom:(char *)(&foo)];
  114.     
  115.     return self;
  116. }
  117.  
  118.  
  119. //
  120. // getSeeds:::
  121. //
  122.  
  123. - getSeeds:(ushort *)s1 :(ushort *)s2 :(ushort *)s3
  124. {
  125.     if((s1 == NULL) || (s2 == NULL) || (s3 == NULL))
  126.     return nil;
  127.  
  128.     *s1 = h1;
  129.     *s2 = h2;
  130.     *s3 = h3;
  131.  
  132.     return self;
  133. }
  134.  
  135.  
  136. //
  137. // makeRandom:
  138. //
  139. // See the Source article for the explanations of these constants:
  140. //
  141.  
  142. - makeRandom:(uchar *)storage
  143. {
  144.     ushort    temp;
  145.     int        i;
  146.     ushort    *out = (ushort *)storage;
  147.     
  148.     do{
  149.     h1 = (F1 * h1) % M1;                    // Update the sections
  150.     h2 = (F2 * h2) % M2;
  151.     h3 = (F2 * h3) % M3;
  152.     } while ((h1 > MAXNUM) || (h2 > MAXNUM) || (h3 > MAXNUM));    // If a section is out of range,
  153.     
  154.     temp = ((h1 + h2 + h3) % RANGE);
  155.     
  156.     for(i = 0; i < 15; i++) {
  157.     do{
  158.         h1 = (F1 * h1) % M1;
  159.         h2 = (F2 * h2) % M2;
  160.         h3 = (F2 * h3) % M3;
  161.     } while ((h1 > MAXNUM) || (h2 > MAXNUM) || (h3 > MAXNUM));
  162.         
  163.     //
  164.     // Save the value, and grab a bit from temp;
  165.     //
  166.     
  167.     out[i] = (ushort)((h1 + h2 + h3) % RANGE) + ((temp & 0x0001) ? 0x8000 : 0x0000);
  168.         temp = temp >> 1;
  169.     }
  170.     
  171.     
  172.     
  173.     return self;
  174. }
  175.  
  176.  
  177. //
  178. // read:
  179. //
  180.  
  181. - read:(NXTypedStream *)stream
  182. {
  183.     int        t1;            // Stuff h's into ints for temporary.
  184.     int        t2;
  185.     int        t3;
  186.     
  187.     [super read:stream];
  188.     
  189.     NXReadTypes(stream, "iii", &t1, &t2, &t3);
  190.     
  191.     h1 = (ushort)t1;
  192.     h2 = (ushort)t2;
  193.     h3 = (ushort)t3;
  194.     
  195.     return self;
  196. }
  197.  
  198.  
  199. //
  200. // write:
  201. //
  202.  
  203. - write:(NXTypedStream *)stream
  204. {
  205.     int        t1 = (int)h1;        // Stuff h's into ints for temporary.
  206.     int        t2 = (int)h2;
  207.     int        t3 = (int)h3;
  208.     
  209.     [super write:stream];
  210.     
  211.     NXWriteTypes(stream, "iii", &t1, &t2, &t3);
  212.  
  213.     return self;
  214. }
  215.  
  216.  
  217. @end
  218.  
  219.  
  220. //
  221. // End of file.
  222. //